let {
    log,
    dir,
    info,
    count,
} = console;

let win = window,
    doc = win.document;

// # 类似jQuery功能类——$

let $ = function (s, queryNode = doc) {
    return new $.prototype.init(s, queryNode);
}

$.prototype = {

    constructor: $,

    init: function (s, queryNode) {
        if (s instanceof Node) {
            this[0] = s;
        } else {
            let eles = this.toArray(queryNode.querySelectorAll(s));
            eles.forEach((el, i) => this[i] = el);
        }
        this.setLength();
    },

    setLength() {
        let digitReg = /\d/;
        this.length = Object.keys(this).filter(key => digitReg.test(key)).length;
    },

    eq(index) {
        return this.constructor(this[index]);
    },

    get(index) {
        return this[index];
    },

    each(cb) {
        let len = this.length;
        for (let i = 0; i < len; i++) cb(this[i], i, this);
    },

    map(cb) {
        let len = this.length,
            ins = this.constructor();
        for (let i = 0; i < len; i++) ins[i] = cb(this[i], i, this);
        ins.setLength();
        return ins;
    },

    reduce(cb, totalVal) {
        let len = this.length,
            i = 0;
        if (arguments.length === 1) {
            i = 1;
            totalVal = this[0];
        }
        for (; i < len; i++) totalVal = cb(totalVal, this[i], i, this);
        return totalVal;
    },

    concat(obj) {
        let len = this.length;
        if (obj instanceof Node) {
            this[len] = obj;
        } else if (typeof obj === 'object' && obj !== null) {
            let objLen = obj.length;
            for (let i = 0; i < objLen; i++) this[len + i] = obj[i];
        }
        this.setLength();
        return this;
    },

    flat(deepth = 1) {
        if (deepth == 0) return this;
        const Ctor = this.constructor;
        return this.reduce((total, now) => {
            return total = total.concat((now instanceof Ctor) ? now.flat(deepth - 1) : now);
        }, new Ctor());
    },

    toArray(arrayLike) {
        return Array.from(arrayLike);
    },

    find(selector) {
        const Ctor = this.constructor;
        return this.map(el => Ctor(selector, el)).flat(Infinity);
    },

    on(event, cb, capture = false) {
        if (typeof event === 'string') {
            this.each(el => el.addEventListener(event, cb, capture));
            return;
        }
        if (typeof event === 'object' && event !== null) {
            this.each(el => Object.keys(event).forEach(name => el.addEventListener(name, event[name], capture)));
        }
    },

    text(content) {
        this.each(el => el.textContent = content);
    },

    html(htmlContent) {
        this.each(el => el.innerHTML = htmlContent);
    },

    attr(name, value) {
        if (typeof name === 'string') {
            this.each(el => el.setAttribute(name, value));
            return;
        }
        if (typeof name === 'object' && name !== null) {
            this.each(el => Object.keys(name).forEach(key => el.setAttribute(key, name[key])));
        }
    },

    removeAttr(name) {
        if (typeof name === 'string') {
            this.each(el => el.removeAttribute(name));
            return;
        }
        if (typeof name === 'object' && name !== null) {
            this.each(el => Object.keys(name).forEach(key => el.removeAttribute(key)))
        }
    },
    append(...eles) {
        this.each(el => el.append(...eles));
    }
}

$.prototype.init.prototype = $.prototype;
